import { ref, reactive, nextTick } from 'vue';
import { XEUtils, TreeUtils } from '@/utils';
import { defAxios as request } from '@/utils/http';

const defaultRootNode = {
	id: '',
	code: '',
	name: '全部',
	childNum: 0,
	children: [],
	parentId: null,
};
const defaultTreeProps = {
	label: 'name',
	value: 'code',
	children: 'children',
};

export const useTreePanelCommonProps = {
	// 树结构数据
	treeData: { type: Array },
	// 树结构面板标题
	treeTitle: { type: String, default: '表单模板' },
	// 树结构数据替换字段
	treeProps: { type: Object },
	// 是否显示标题
	showTitle: { type: Boolean, default: true },
	// 是否默认展开所有节点
	expandAll: { type: Boolean, default: false },
	// 输入框文本提示
	placeholder: { type: String, default: '请输入关键词' },
	// 是否显示顶部节点
	showRootNode: { type: Boolean, default: true },
	// 顶部节点内容描述
	rootNodeText: { type: String, default: '全部' },
	// 服务请求配置
	serverConfig: { type: [Object, Function] },
	// 自定义响应
	responseHandle: { type: [Function] },
	// 是否在点击节点的时候展开或者收缩节点， 默认值为 true，如果为 false，则只有点箭头图标的时候才会展开或者收缩节点
	expandOnClickNode: { type: Boolean, default: false },
};
export const useTreePanelOperateHook = ({ props, emits, rootNode }) => {
	const loading = ref(false);
	const sTreeData = ref([]);
	const filterText = ref('');
	const sTreeProps = reactive({});
	const asideTreeRef = ref(null);
	const currentNodeKey = ref('');
	// 树节点展开信息
	const treeExpandedKeys = ref([]);
	// 树节点默认展开信息
	const defaultExpandedKeys = ref([]);
	// 转换后的树节点信息
	const treeState = reactive({
		treeNodeMap: {},
		treeExpandMap: {},
	});

	watch(filterText, (val) => {
		asideTreeRef.value.filter(val);
	});

	const loadTree = async () => {
		initTreeProps();
		loading.value = true;
		const treeData = await getTreeData();
		loading.value = false;
		initTreeExpanded(treeData);
		initTreeData(treeData);
		initTreeFirstNode();
	};
	const reloadTree = async (getTreeData) => {
		defaultExpandedKeys.value = [];
		const treeData = await getTreeData();
		initTreeData(treeData);
		if (currentNodeKey.value) {
			nextTick(() => {
				if (asideTreeRef.value) asideTreeRef?.value.setCurrentKey(currentNodeKey.value);
			});
		}
		defaultExpandedKeys.value = toRaw(treeExpandedKeys.value);
		setExpanded(toRaw(treeExpandedKeys.value));
	};
	const initTreeData = (treeData) => {
		const { showRootNode, rootNodeText } = props;
		const { nodeMap, expandMap } = TreeUtils.transfData(treeData, {
			props: { label: sTreeProps.label, value: sTreeProps.value },
			showCode: false,
		});
		treeState.treeNodeMap = XEUtils.clone(nodeMap, true);
		treeState.treeExpandMap = XEUtils.clone(expandMap, true);
		if (showRootNode) {
			let resultRootNode = XEUtils.clone(rootNode || defaultRootNode, true);
			resultRootNode.menuName = rootNodeText;
			resultRootNode.children = treeData;
			sTreeData.value = [resultRootNode];
		} else {
			sTreeData.value = treeData;
		}
	};
	const initTreeProps = () => {
		const resultProps = XEUtils.clone(defaultTreeProps, true);
		Object.keys(resultProps).forEach((key) => {
			sTreeProps[key] = props.treeProps ? props.treeProps[key] : resultProps[key];
		});
	};
	const initTreeExpanded = (treeData) => {
		const defaultKeys = treeData.map((item) => item[sTreeProps.value]);
		treeExpandedKeys.value = defaultKeys;
		defaultExpandedKeys.value = defaultKeys;
	};
	const initTreeFirstNode = () => {
		setTimeout(() => {
			handleNodeChange(sTreeData.value[0]);
		}, 300);
	};
	/**
	 * 设置树结构展开
	 * @param {Array} targetKeys 需要展开的key
	 */
	const setExpanded = (targetKeys) => {
		const treeNodesMap = asideTreeRef.value.store.nodesMap;
		for (let node in treeNodesMap) {
			if (targetKeys.includes(node)) {
				treeNodesMap[node].expanded = true;
			} else {
				treeNodesMap[node].expanded = false;
			}
		}
	};
	/**
	 * 节点搜索时
	 *
	 * @param {*} value
	 * @param {*} data
	 */
	const handleFilter = (value, data) => {
		if (!value) return true;
		return data[sTreeProps.value].includes(value) || data[sTreeProps.label].includes(value);
	};
	/**
	 * 节点被展开时触发的事件
	 * 传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
	 * @param {*} data
	 * @param {*} treeNode
	 * @param {*} nodeRef
	 */
	const handleExpand = (data, treeNode, nodeRef) => {
		let keysSet = new Set([...toRaw(treeExpandedKeys.value)]);
		keysSet.add(data[sTreeProps.value]);
		treeExpandedKeys.value = [...keysSet];
	};
	/**
	 * 节点被关闭时触发的事件
	 * 传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身
	 * @param {*} data
	 * @param {*} treeNode
	 * @param {*} nodeRef
	 */
	const handleCollapse = (data, treeNode, nodeRef) => {
		let keysSet = new Set([...toRaw(treeExpandedKeys.value)]);
		keysSet.delete(data[sTreeProps.value]);
		treeExpandedKeys.value = [...keysSet];
	};
	/**
	 * 树节点点击
	 */
	const handleNodeClick = (data, treeNode, treeVNode, event) => {
		currentNodeKey.value = data[sTreeProps.value];
		emitNodeClick(toRaw({ ...data }), treeNode);
	};
	/**
	 * 树节点选中变化
	 */
	const handleNodeChange = (data, treeNode) => {
		emitNodeChange(toRaw({ ...data }), treeNode);
	};

	// 请求服务
	const getTreeData = () => {
		const { treeData, serverConfig, responseHandle } = props;
		return new Promise(async (reslove) => {
			if (treeData) {
				reslove(treeData);
			} else {
				if (serverConfig) {
					const { url, method, params } = serverConfig;
					const options = {
						url,
						method: method || 'post',
					};
					if (options.method === 'post') {
						options['data'] = params;
					} else {
						options['params'] = params;
					}
					request(options)
						.then((res) => {
							const { data, msg, code } = res;
							let result = [];
							if (code === 200) {
								result = responseHandle ? responseHandle(data) : data;
							} else {
								console.error(msg);
							}
							reslove(result);
						})
						.catch((err) => {
							console.error(err);
							reslove([]);
						});
				} else {
					reslove([]);
				}
			}
		});
	};

	// ----- emits 方法的定义
	const emitNodeClick = (data, treeNode) => {
		emits('nodeClick', data, treeNode);
	};
	const emitNodeChange = (data, treeNode) => {
		emits('currentChange', data, treeNode);
	};

	return {
		loading,
		sTreeData,
		filterText,
		sTreeProps,
		asideTreeRef,
		currentNodeKey,
		defaultExpandedKeys,

		loadTree,
		reloadTree,
		handleFilter,
		handleExpand,
		handleCollapse,
		handleNodeClick,
		handleNodeChange,
	};
};
